package com.gorillalogic.scrummonkey.test {
	import com.gorillalogic.scrummonkey.dms.DmsUtils;
	import com.gorillalogic.scrummonkey.dms.Project;
	import com.gorillalogic.scrummonkey.dms.ProjectService;
	import com.gorillalogic.scrummonkey.dms.Release;
	import com.gorillalogic.scrummonkey.dms.ReleaseService;
	
	import mx.collections.ArrayCollection;
	
	import org.flexunit.Assert;

	public class ProjectTest extends BaseTest {

		/**
		 * Create P and verify success
		 */
		[Test(async,order=1)]
		public function create():void {
			var p:Project = new Project('projecttest-proj1','desc-proj1');
			callAndThenOrFault(ProjectService.service.createProject(p), create2);
		}

		private function create2(data:Object, passThroughData:Object):void {
			//get project by name & wait for response
			callAndThenOrFault(ProjectService.service.getByName('projecttest-proj1'), create3);
		}

		private function create3(data:Object, passThroughData:Object):void {
			//verify getByName returned one project
			var projects:ArrayCollection = data.result as ArrayCollection;
			Assert.assertEquals('Bad number of projects', 1, projects.length);

			//verify project
			var project:Project = projects.getItemAt(0) as Project;
			Assert.assertEquals('Bad project name', 'projecttest-proj1', project.name);
			Assert.assertEquals('Bad project description', 'desc-proj1', project.description);
		}

		/**
		 * Create one child R under P
		 */
		[Test(async,order=2)]
		public function createRelease():void {
			//get project by name & wait for response
			callAndThenOrFault(ProjectService.service.getByName('projecttest-proj1'), createRelease2);
		}

		private function createRelease2(data:Object, passThroughData:Object):void {
			var project:Project = (data.result as ArrayCollection).getItemAt(0) as Project;
			Assert.assertEquals('Bad project name', 'projecttest-proj1', project.name);

			//create release
			var r:Release = new Release('rel1','desc-rel1');

			//WARNING: because 'project' is already a managed instance, this will NOT work:
			//
			//project.addRelease(r);
			//callAndThenOrFault(ReleaseService.service.createRelease(r), waitForCreateRelease);
			//
			//Because createRelease throws an 'item already exists' fault because
			//project.addRelease(r) forces r over the wire (since project is managed),
			//thus when createRelease is called it's already there

			//Normally, we can just call addRelease and forget about it, but if we must
			//guarantee completion...then use a transaction
			callAndThenOrFault(DmsUtils.doTxn(ReleaseService.service,
				function ():void {
					project.addRelease(r);
				}), createRelease3);
		}

		private function createRelease3(data:Object, passThroughData:Object):void {
			//get project by name & wait for response
			callAndThenOrFault(ProjectService.service.getByName('projecttest-proj1'), createRelease4);
		}

		private function createRelease4(data:Object, passThroughData:Object):void {
			var project:Project = (data.result as ArrayCollection).getItemAt(0) as Project;
			Assert.assertEquals('Bad project name', 'projecttest-proj1', project.name);

			//verify release
			Assert.assertEquals('Bad number of releases', 1, project.releases.length);
			var release:Release = project.releases.getItemAt(0) as Release;
			Assert.assertEquals('Bad release name', 'rel1', release.name);
			Assert.assertEquals('Bad release description', 'desc-rel1', release.description);
			Assert.assertEquals('Bad release project name', 'projecttest-proj1', release.project.name);
		}

		/**
		 * Cleanup P and child R
		 */
		[Test(async,order=3)]
		public function cleanup():void {
			callAndThenOrFault(ProjectService.service.getByName('projecttest-proj1'), cleanup2);
		}

		private function cleanup2(data:Object, passThroughData:Object):void {
			var project:Project = (data.result as ArrayCollection).getItemAt(0) as Project;
			Assert.assertEquals('Bad project name', 'projecttest-proj1', project.name);

			callAndThenOrFault(ProjectService.service.deleteProject(project), cleanup3);
		}

		private function cleanup3(data:Object, passThroughData:Object):void {
			callAndThenOrFault(ProjectService.service.getByName('projecttest-proj1'), cleanup4);
			callAndThenOrFault(ReleaseService.service.getByName('rel1'), cleanup4);
		}

		private function cleanup4(data:Object, passThroughData:Object):void {
			var entities:ArrayCollection = data.result as ArrayCollection;
			Assert.assertEquals('Cleanup failed', 0, entities.length);
		}
	}
}